package com.wistech.commons.utils;

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author Liuye
 */
public class StringUtils {
	public static final Charset GBK = Charset.forName("GBK");
	public static final Charset UTF_8 = Charset.forName("UTF-8");
	public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");

	private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6',
			'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

	/**
	 * 按中文两字符来截取子字符串
	 * 
	 * @param beginIndex
	 *            the beginning index, inclusive.
	 * @return the specified substring.
	 * @exception IndexOutOfBoundsException
	 *                if <code>beginIndex</code> is negative or larger than the
	 *                length of this <code>String</code> object.
	 */
	public static String substring(String str, int beginIndex) {
		return substring(str, beginIndex, str.length());
	}

	/**
	 * 按中文两字符来截取子字符串
	 * 
	 * @param beginIndex
	 *            the beginning index, inclusive.
	 * @param endIndex
	 *            the ending index, exclusive.
	 * @return the specified substring.
	 * @return
	 */
	public static String substring(String str, int beginIndex, int endIndex) {
		if (str == null) {
			return "";
		}
		String resu = "";
		int beg = 0;
		int end = 0;
		int count1 = 0;
		char[] temp = new char[str.length()];
		str.getChars(0, str.length(), temp, 0);
		boolean[] bol = new boolean[str.length()];
		for (int i = 0; i < temp.length; i++) {
			bol[i] = false;
			if ((int) temp[i] > 255) {// 说明是中文
				count1++;
				bol[i] = true;
			}
		}

		if (beginIndex > str.length() + count1) {
			resu = null;
		}
		if (beginIndex > endIndex) {
			resu = null;
		}
		if (beginIndex < 1) {
			beg = 0;
		} else {
			beg = beginIndex - 1;
		}
		if (endIndex > str.length() + count1) {
			end = str.length() + count1;
		} else {
			end = endIndex;// 在substring的末尾一样
		}
		// 下面开始求应该返回的字符串
		if (resu != null) {
			if (beg == end) {
				int count = 0;
				if (beg == 0) {
					if (bol[0] == true) {
						resu = null;
					} else {
						resu = new String(temp, 0, 1);
					}
				} else {
					int len = beg;// zheli
					for (int y = 0; y < len; y++) {// 表示他前面是否有中文,不管自己
						if (bol[y] == true) {
							count++;
						}
						len--;// 想明白为什么len--
					}
					// for循环运行完毕后，len的值就代表在正常字符串中，目标beg的上一字符的索引值
					if (count == 0) {// 说明前面没有中文
						if ((int) temp[beg] > 255)// 说明自己是中文
						{
							resu = null;// 返回空
						} else {
							resu = new String(temp, beg, 1);
						}
					} else {// 前面有中文，那么一个中文应与2个字符相对
						if ((int) temp[len + 1] > 255)// 说明自己是中文
						{
							resu = null;// 返回空
						} else {
							resu = new String(temp, len + 1, 1);
						}
					}
				}
			} else {// 下面是正常情况下的比较
				int temSt = beg;
				int temEd = end - 1;// 这里减掉一
				for (int i = 0; i < temSt; i++) {
					if (bol[i] == true) {
						temSt--;
					}
				}// 循环完毕后temSt表示前字符的正常索引
				for (int j = 0; j < temEd; j++) {
					if (bol[j] == true) {
						temEd--;
					}
				}// 循环完毕后temEd-1表示最后字符的正常索引
				if (bol[temSt] == true)// 说明是字符，说明索引本身是汉字的后半部分，那么应该是不能取的
				{
					int cont = 0;
					for (int i = 0; i <= temSt; i++) {
						cont++;
						if (bol[i] == true) {
							cont++;
						}
					}
					if (beginIndex == cont)// 是偶数不应包含,如果pstart<cont则要包含
					{
						temSt++;// 从下一位开始
					}
				}
				if (bol[temEd] == true) {// 因为temEd表示substring
					// 的最面参数，此处是一个汉字，下面要确定是否应该含这个汉字
					int cont = 0;
					for (int i = 0; i <= temEd; i++) {
						cont++;
						if (bol[i] == true) {
							cont++;
						}
					}
					if (endIndex < cont)// 是汉字的前半部分不应包含
					{
						temEd--;// 所以只取到前一个
					}
				}
				if (temSt == temEd) {
					resu = new String(temp, temSt, 1);
				} else if (temSt > temEd) {
					resu = null;
				} else {
					resu = str.substring(temSt, temEd + 1);
				}
			}
		}
		return resu;// 返回结果
	}

	public static String join(Object[] array, String separator) {
		if (array == null) {
			return null;
		}
		int arraySize = array.length;
		StringBuilder buffer = new StringBuilder();

		for (int i = 0; i < arraySize; i++) {
			if (i > 0) {
				buffer.append(separator);
			}
			if (array[i] != null) {
				buffer.append(array[i]);
			}
		}
		return buffer.toString();
	}

	/**
	 * 按ascii码计算中英文字符串长度
	 * 
	 * @return
	 */
	public static int getAsciiLength(String str) {
		return new String(str.getBytes(GBK), ISO_8859_1).length();
	}

	public static String md5Hex(String data) {
		if (data == null) {
			throw new IllegalArgumentException("data must not be null");
		}

		byte[] bytes = digest("MD5", data);

		return toHexString(bytes);
	}

	public static String sha1Hex(String data) {
		if (data == null) {
			throw new IllegalArgumentException("data must not be null");
		}

		byte[] bytes = digest("SHA1", data);

		return toHexString(bytes);
	}

	private static String toHexString(byte[] bytes) {
		int l = bytes.length;

		char[] out = new char[l << 1];

		for (int i = 0, j = 0; i < l; i++) {
			out[j++] = DIGITS[(0xF0 & bytes[i]) >>> 4];
			out[j++] = DIGITS[0x0F & bytes[i]];
		}

		return new String(out);
	}

	private static byte[] digest(String algorithm, String data) {
		MessageDigest digest;
		try {
			digest = MessageDigest.getInstance(algorithm);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}

		byte[] bytes = digest.digest(data.getBytes());
		return bytes;
	}
}
